
#include "stdafx.h"
#include "tick.h"

//static variable & function
LONGLONG Dbl2Int(double v)
{
	LONGLONG i = (LONGLONG)v; if (i > v) i--;
	return i;
}
LONGLONG DblRound(double v)
{
	return v >= 0 ? (LONGLONG)(v + 0.5) : (LONGLONG)(v - 0.5);
}

static LARGE_INTEGER freq;
static double freqMS;
static bool useCount = false;
static CRawTick DayRawTick = CRawTick::ms(24 * 60 * 60 * 1000);

void TICK::init(TICK_METHOD method)
{
	switch (method)
	{
	case Auto:
	case UseCount:
		useCount = QueryPerformanceFrequency(&freq) ? true : false;
		break;
	case UseTick:
		useCount = false; break;
	}
	if (useCount) freqMS = (double)freq.QuadPart / 1000;
	DayRawTick = CRawTick::ms(24 * 60 * 60 * 1000);
}

bool TICK::highPerformance()
{
	return useCount;
}

const TICK TICK::Now(intptr_t addms)
{
	TICK t;
	if (useCount)
	{
		QueryPerformanceCounter(&t.m_count);
		if (addms) t.m_count.QuadPart = DblRound(t.m_count.QuadPart + freqMS * addms);
	}
	else
	{
#ifdef _WIN64
		t.m_tick = ::GetTickCount64() + addms;
#else
		t.m_tick = ::GetTickCount() + addms;
#endif
	}
	return t;
}



//DFTick
void DFTick::setDiff(double value)
{
	if (useCount)
		countDiff.QuadPart = DblRound(freqMS*value);
	else
		tickDiff = (intptr_t)DblRound(value);
}
double DFTick::getDiff() const
{
	if (useCount)
		return (double)countDiff.QuadPart / freqMS;
	else
		return (double)tickDiff;
}
DFTick::DFTick(intptr_t value, bool valueIsMs)
{
	if (useCount)
	{
		if (valueIsMs)
			countDiff.QuadPart = DblRound(freqMS*value);
		else
			countDiff.QuadPart = (LONGLONG)(freq.QuadPart*value);
	}
	else
	{
		if (valueIsMs)
			tickDiff = value;
		else
			tickDiff = value * 1000;
	}
}
intptr_t DFTick::diff(bool valueIsMs) const
{
	if (useCount)
	{
		if (valueIsMs)
			return (intptr_t)Dbl2Int((double)countDiff.QuadPart / freqMS);
		else
			return (intptr_t)Dbl2Int((double)countDiff.QuadPart / freq.QuadPart);
	}
	else
	{
		if (valueIsMs)
			return tickDiff;
		else
			return (intptr_t)Dbl2Int((double)tickDiff / 1000);
	}
}
bool DFTick::operator == (intptr_t ms) const
{
	if (useCount)
		return countDiff.QuadPart == (ms ? Dbl2Int(freqMS*ms) : 0);
	else
		return tickDiff == ms;
}
bool DFTick::operator != (intptr_t ms) const
{
	if (useCount)
		return countDiff.QuadPart != (ms ? Dbl2Int(freqMS*ms) : 0);
	else
		return tickDiff != ms;
}
bool DFTick::operator < (intptr_t ms) const
{
	if (useCount)
		return countDiff.QuadPart < (ms ? Dbl2Int(freqMS*ms) : 0);
	else
		return tickDiff < ms;
}
bool DFTick::operator > (intptr_t ms) const
{
	if (useCount)
		return countDiff.QuadPart > (ms ? Dbl2Int(freqMS*ms) : 0);
	else
		return tickDiff > ms;
}
bool DFTick::operator <= (intptr_t ms) const
{
	if (useCount)
		return countDiff.QuadPart <= (ms ? Dbl2Int(freqMS*ms) : 0);
	else
		return tickDiff <= ms;
}
bool DFTick::operator >= (intptr_t ms) const
{
	if (useCount)
		return countDiff.QuadPart >= (ms ? Dbl2Int(freqMS*ms) : 0);
	else
		return tickDiff >= ms;
}
const DFTick DFTick::operator + (const DFTick & df) const
{
	DFTick result;
	if (useCount)
		result.countDiff.QuadPart = countDiff.QuadPart + df.countDiff.QuadPart;
	else
		result.tickDiff = tickDiff + df.tickDiff;
	return result;
}
const DFTick DFTick::operator - (const DFTick & df) const
{
	DFTick result;
	if (useCount)
		result.countDiff.QuadPart = countDiff.QuadPart - df.countDiff.QuadPart;
	else
		result.tickDiff = tickDiff - df.tickDiff;
	return result;
}
void DFTick::operator += (const DFTick & df)
{
	if (useCount)
		countDiff.QuadPart += df.countDiff.QuadPart;
	else
		tickDiff += df.tickDiff;
}
void DFTick::operator -= (const DFTick & df)
{
	if (useCount)
		countDiff.QuadPart -= df.countDiff.QuadPart;
	else
		tickDiff -= df.tickDiff;
}






//TICK
intptr_t TICK::miSeconds() const
{
	if (useCount)
		return (intptr_t)DblRound((double)m_count.QuadPart / freqMS);
	else
		return (intptr_t)m_tick;
}
bool TICK::IsEmpty() const
{
	return useCount ? (m_count.QuadPart == 0) : (m_tick == 0);
}
bool TICK::IsAvailable() const
{
	return useCount ? (m_count.QuadPart != 0) : (m_tick != 0);
}
bool TICK::operator == (const TICK & t) const
{
	if (useCount)
		return m_count.QuadPart == t.m_count.QuadPart;
	else
		return m_tick == t.m_tick;
}
bool TICK::operator != (const TICK & t) const
{
	if (useCount)
		return m_count.QuadPart != t.m_count.QuadPart;
	else
		return m_tick != t.m_tick;
}
bool TICK::operator < (const TICK & t) const
{
	if (useCount)
		return m_count.QuadPart < t.m_count.QuadPart;
	else
		return (intptr_t)(m_tick - t.m_tick) < 0;
}
bool TICK::operator > (const TICK & t) const
{
	if (useCount)
		return m_count.QuadPart > t.m_count.QuadPart;
	else
		return (intptr_t)(m_tick - t.m_tick) > 0;
}
bool TICK::operator <= (const TICK & t) const
{
	if (useCount)
		return m_count.QuadPart <= t.m_count.QuadPart;
	else
		return (intptr_t)(m_tick - t.m_tick) <= 0;
}
bool TICK::operator >= (const TICK & t) const
{
	if (useCount)
		return m_count.QuadPart >= t.m_count.QuadPart;
	else
		return (intptr_t)(m_tick - t.m_tick) >= 0;
}
const TICK TICK::operator + (const DFTick & df) const
{
	TICK result;
	if (useCount)
		result.m_count.QuadPart = m_count.QuadPart + df.countDiff.QuadPart;
	else
		result.m_tick = m_tick + df.tickDiff;
	return result;
}
const TICK TICK::operator - (const DFTick & df) const
{
	TICK result;
	if (useCount)
		result.m_count.QuadPart = m_count.QuadPart - df.countDiff.QuadPart;
	else
		result.m_tick = m_tick - df.tickDiff;
	return result;
}
void TICK::operator += (const DFTick & df)
{
	if (useCount)
		m_count.QuadPart += df.countDiff.QuadPart;
	else
		m_tick += df.tickDiff;
}
void TICK::operator -= (const DFTick & df)
{
	if (useCount)
		m_count.QuadPart -= df.countDiff.QuadPart;
	else
		m_tick -= df.tickDiff;
}
const DFTick TICK::operator - (const TICK & t) const
{
	DFTick result;
	if (useCount)
		result.countDiff.QuadPart = m_count.QuadPart - t.m_count.QuadPart;
	else
		result.tickDiff = (intptr_t)(m_tick - t.m_tick);
	return result;
}




//CRawTick
const CRawTick CRawTick::CheckValid(const CRawTick &t)
{
	CRawTick result = t;
	if (useCount)
	{
		if (result.m_count.QuadPart < 0)
			result.m_count.QuadPart += (LONGLONG)((DayRawTick.m_count.QuadPart - result.m_count.QuadPart - 1) / DayRawTick.m_count.QuadPart)*DayRawTick.m_count.QuadPart;
		if (result.m_count.QuadPart >= DayRawTick.m_count.QuadPart)
			result.m_count.QuadPart %= DayRawTick.m_count.QuadPart;
	}
	else
	{
		if ((intptr_t)result.m_tick < 0)
			result.m_tick += (intptr_t)((DayRawTick.m_tick - result.m_tick - 1) / DayRawTick.m_tick)*DayRawTick.m_tick;
		if ((intptr_t)result.m_tick >= (intptr_t)DayRawTick.m_tick)
			result.m_tick %= DayRawTick.m_tick;
	}
	return result;
}
const CPlainTime CRawTick::toPlain() const
{
	CPlainTime result; uintptr_t misec = miSeconds();
	result.ms = (unsigned int)(misec % 1000); misec /= 1000;
	result.second = (unsigned int)(misec % 60); misec /= 60;
	result.minute = (unsigned int)(misec % 60); misec /= 60;
	result.hour = (unsigned int)(misec % 24);
	return result;
}
void CRawTick::SetMiSeconds(intptr_t ms)
{
	if (useCount)
		m_count.QuadPart = DblRound(freqMS*ms);
	else
		m_tick = ms;
}
